package sketch.main;

import java.io.File;
import java.util.LinkedList;
import java.util.List;

import plume.Option;
import plume.Options;
import plume.Unpublicized;
import sketch.util.SketchUtil;

public class SketchTestOptions {

	@Option(value="Print usage of SketchTest options")
	public static boolean help = false;
	
	@Option(value="Print all debugging information")
	public static boolean verbose = false;
	
	@Option(value = "Remove all intermediate output")
	public static boolean release = true;
	
	@Option(value = "Delete all intermediate files")
	public static boolean difiles = false;
	
	@Option(value="The input test sketch")
	public static String test_sketch = null;
	
	@Option(value="The full class name of the test sketch")
	public static String junit_name = null;
	
	@Option(value="Dir containing all test sketches")
	public static String test_sketch_dir = null;
	
	@Option(value="The output dir for generated tests")
	public static String output_dir = "./output/";
	
	@Unpublicized
	@Option(value="The dir for storing all intermediate result")
	public static String dir_in_classpath = "./tmp";
	
	@Option(value="The time (in seconds) for random test generation (required when using random values)")
	public static int random_time = -1;
	
	@Option(value="The time (in seconds) for fuzz (required when using random values)")
	public static int fuzz_time = -1;
	
	@Option(value="The method to be executed symbolically")
	public static String symbolic_method = null;
	
	@Option(value="The class treated to be symbolically")
	public static String symbolic_class = null;
	
	@Option(value="The entry class for invoking tests")
	public static String entry_junit = null;
	
	@Option(value="The output JUnit class name")
	public static String output_test_name = "SketchGeneratedTest";
	/**
	 * Parse the argument options and assign the value to the right place
	 * */
	public void parseArgsAndConfigSketchTest(String[] args) {
		Options options = new Options("SketchTest usage options.", SketchTestOptions.class);
		String[] file_args = options.parse_or_usage(args);
		//errors in parsing the arguments
		if(file_args.length != 0) {
			SketchUtil.flushToStd(file_args);
			System.exit(1);
		}
		String[] errorMsg = this.checkArgumentValidity();
		if(errorMsg.length != 0) {
			SketchUtil.flushToStd(errorMsg);
			options.print_usage();
			System.exit(1);
		}
		//assign the arguments to the right place
		this.configureSketchTest();
	}
	
	private String[] checkArgumentValidity() {
		List<String> error_msgs = new LinkedList<String>();
		String sketch_test = SketchTestOptions.test_sketch;
		String sketch_test_dir = SketchTestOptions.test_sketch_dir;
		if(sketch_test == null && sketch_test_dir == null) {
			error_msgs.add("Must specify the test sketch path using --test_sketch or --test_sketch_dir.");
		} else if (sketch_test != null && sketch_test_dir != null) {
			error_msgs.add("Can not specify both --test_sketch and --test_sketch_dir");
		} else {
			if(sketch_test != null) {
		      File f = new File(sketch_test);
		      if(!f.exists()) {
		    	error_msgs.add("The test sketch your provide: " + sketch_test + " does not exist.");
		      }
		      if(junit_name == null) {
		    	  error_msgs.add("The junit name (class name of the test sketch must be specified" +
		    	  		" using --junit_name");
		      }
			}
			if(sketch_test_dir != null) {
				File f = new File(sketch_test_dir);
				if(!f.exists()) {
					error_msgs.add("The test sketch dir your provide: " + sketch_test_dir + " does not exist.");
				}
				if(entry_junit == null) {
					error_msgs.add("You must specify a entry junit class to run all the tests.");
				}
			}
		}
		
		//check the symbolic  settings
		if(symbolic_method != null && symbolic_class == null) {
				error_msgs.add("You have specified symbolic_method: " + symbolic_method
						+ ", you also need to specify symbolic_class: --symbolic_class");
		}
		if(symbolic_class != null && symbolic_method == null) {
			error_msgs.add("You have specified symbolic_class: " + symbolic_class
					+ ", you also need to specify symbolic_class: --symbolic_method");
		}
		if(random_time != -1 && fuzz_time == -1) {
			error_msgs.add("You have specified random time: " + random_time + ", you also need to specify" +
					" fuzz_time: --fuzz_time");
		}
		if(fuzz_time != -1 && random_time == -1) {
			error_msgs.add("You have specified fuzz time: " + fuzz_time + ", you also need to specify" +
					" random_time: --random_time");
		}
		
		if(!SketchUtil.isDirInClasspath(SketchTestOptions.output_dir)) {
			error_msgs.add("The dir: " + output_dir + " is not in your classpath, please set it by --output_dir option");
		}
		
		return (String[]) error_msgs.toArray(new String[0]);
	}
	
	private void configureSketchTest() {
		//make it as release
		GeneratingTests.release = SketchTestOptions.release;
	}
	
	public static void main(String[] args) {
		args = new String[]{"--test_sketch=./MaiknTest.java"};
		SketchTestOptions options = new SketchTestOptions();
		options.parseArgsAndConfigSketchTest(args);
	}
}